<?php
declare(strict_types=1);

namespace app\common\business;

use app\common\model\Category as CategoryModel;
use app\common\model\Module as ModuleModel;
use app\common\model\ModuleField as ModuleFieldModel;
use app\common\model\RelationAttributeCategory as RelationAttributeCategoryModel;
use app\common\model\Attribute as AttributeModel;
use app\common\model\AttributeValue as AttributeValueModel;
use app\common\model\CommonBase as CommonBaseModel;
use app\common\model\Article as ArticleModel;
use think\facade\Cache;
use Exception;

class Category extends CommonBase
{
    private $_categoryObj = null;
    private const _LEVEL_PREFIX       = "├─ ";
    private const _LAST_LEVEL_PREFIX  = "└─ ";
    private const _FIRST_LEVEL_PREFIX = "│　";

    public function __construct(string $websiteCode)
    {
        $this->_categoryObj = new CategoryModel([], $websiteCode);
        $this->_websiteCode = $websiteCode;
    }

    /*** public methods ***/

    public function getCategories(array $where = []): array
    {
        $res = [];
        try {
            $moduleModule = new ModuleModel([], $this->_websiteCode);
            $modules      = $moduleModule->getAllModule();

            $categories = $this->_categoryObj->getAllCategory('', $where);

            $categoryIds = [];
            foreach ($categories as $category) {
                $categoryIds [] = $category['id'];
            }
            $relationAttributeCategoryModel = new RelationAttributeCategoryModel([], $this->_websiteCode);
            $relationAttributeCategories    = $relationAttributeCategoryModel->getAllRelationAttributeCategory([['category_id', 'in', $categoryIds]])->toArray();
            $relationAttributeCategoryMap   = [];
            $attributeIds                   = [];
            foreach ($relationAttributeCategories as $relationAttributeCategory) {
                if (!in_array($relationAttributeCategory['attribute_id'], $attributeIds)) {
                    $attributeIds[] = $relationAttributeCategory['attribute_id'];
                }

                $relationAttributeCategoryMap[$relationAttributeCategory['category_id']][] = $relationAttributeCategory['attribute_id'];
            }

            $attributeValueModel = new AttributeValueModel([], $this->_websiteCode);
            $attributeValues     = $attributeValueModel->getAllAttributeValue([['attribute_id', 'in', $attributeIds]]);

            $attributeModel = new AttributeModel([], $this->_websiteCode);
            $attributes     = $attributeModel->getAllAttribute([['id', 'in', $attributeIds]]);

            $categoryHasImageAttributeMap = [];
            foreach ($categories as $category) {
                $categoryHasImageAttributeMap[$category['id']] = 0;
                $relationAttributeCategory                     = $relationAttributeCategoryMap[$category['id']] ?? [];
                foreach ($attributes as $attribute) {
                    if (in_array($attribute['id'], $relationAttributeCategory) && $attribute['attribute_type'] == AttributeModel::IS_PICTURE_ATTRIBUTE) {
                        $categoryHasImageAttributeMap[$category['id']] = $attribute['id'];
                        break;
                    }
                }
            }

            $activeAttributes = [];
            foreach ($attributes as $key => $attribute) {
                $attributeId = $attribute['id'];
                foreach ($attributeValues as $attributeValue) {
                    if ($attributeValue['attribute_id'] == $attributeId && count($attributeValue) > 0) {
                        if (!isset($activeAttributes[$attributeId])) {
                            $activeAttributes[$attributeId] = $attribute;
                        }

                        $activeAttributes[$attributeId]['values'][] = $attributeValue;
                    }
                }
            }

            foreach ($categories as $category) {
                $category['hasImageAttribute'] = $categoryHasImageAttributeMap[$category['id']] != 0;
                $category['imageAttributeId']  = $categoryHasImageAttributeMap[$category['id']];
                $relationAttributeCategory     = $relationAttributeCategoryMap[$category['id']] ?? [];

                $category['attributes']        = [];
                foreach ($activeAttributes as $activeAttribute) {
                    if (in_array($activeAttribute['id'], $relationAttributeCategory)) {
                        $category['attributes'][$activeAttribute['id']] = $activeAttribute;
                    }
                }


                // 当前的所有父级
                $category['parents']    = [];
                $parents = $this->_getCurCategoryParents($categories, $category['id']);
                for ($i = count($parents) - 1; $i >= 0; $i--) {
                    $category['parents'][] = $parents[$i];
                }

                // 当前的顶级
                $topParent = $parents[count($parents) - 1];

                // 顶级的所有子级
                $children = [$topParent];
                $children = array_merge($children, $this->_getCurCategoryChildren($categories, $topParent['id']));

                $category['categories'] = $this->_wrapTitle($children, $modules);

                $res[$category['id']] = $category;
            }

            // echo '<pre>';
            // print_r($res);
            // exit;
            return $res;
        } catch (Exception $e) {
            logErr('读取所有栏目失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }
        return [];
    }

    public function getAllCategory(array $where = []): array
    {
        try {
            $categories = $this->_categoryObj->getAllCategory('', $where);
            $count      = count($categories);

            $res = $this->_getCurCategoryChildren($categories, 0);

            $moduleModule = new ModuleModel([], $this->_websiteCode);
            $modules      = $moduleModule->getAllModule();

            return ['rows' => $this->_wrapTitle($res, $modules), 'count' => $count];

        } catch (Exception $e) {
            logErr('读取所有栏目失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [];
    }

    public function addCategory(string $cdnDomain, array $data): bool
    {
        try {
            $categories = $this->_categoryObj->getAllCategory();
            $parents    = $this->_getCurCategoryParents($categories, $data['pid']);

            $uris = [];
            for ($i = count($parents) - 1; $i >= 0; $i--) {
                $tempSeoUrl = strtolower($parents[$i]['seo_url']);
                $tempSeoUrl = str_replace(' ', '-', $tempSeoUrl);
                $tempSeoUrl = str_replace('/', '', $tempSeoUrl);
                $uris []    = $tempSeoUrl;
            }

            $seoUrl      = strtolower($data['seo_url']);
            $seoUrl      = str_replace(' ', '-', $seoUrl);
            $seoUrl      = str_replace('/', '', $seoUrl);
            $uris[]      = $seoUrl;
            $data['uri'] = '/' . implode('/', $uris);

            return $this->_categoryObj->addCategory($cdnDomain, $data);
        } catch (Exception $e) {
            logErr('添加栏目失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return false;
    }

    public function findCategoryById($cdnDomain, int $id): array
    {
        $category = [];
        try {
            $category = $this->_categoryObj->findCategoryById($id);

            if (empty($category)) {
                return [];
            }

            $category['fullImage']          = $category['image'] ? $cdnDomain . '/' . $category['image'] : '';
            $category['fullIntroduceImage'] = $category['introduce_image'] ? $cdnDomain . '/' . $category['introduce_image'] : '';
            $category['fullNoteImage']      = $category['note_image'] ? $cdnDomain . '/' . $category['note_image'] : '';
            $category['introduce_content']  = str_replace('{cdnDomain}', $cdnDomain, $category['introduce_content']);
            $category['note']               = str_replace('{cdnDomain}', $cdnDomain, $category['note']);

            // 关联的属性
            $hasImageAttribute              = false;
            $imageAttributeId               = 0;
            $attributeIds                   = [];
            $relationAttributeCategoryModel = new RelationAttributeCategoryModel([], $this->_websiteCode);
            $relationAttributeCategoryObj   = $relationAttributeCategoryModel->getAllRelationAttributeCategory(['category_id' => $id]);
            $relationAttributeCategory      = $relationAttributeCategoryObj->toArray();
            foreach ($relationAttributeCategory as $v) {
                $attributeIds[] = $v['attribute_id'];
            }

            $attributeValueModel = new AttributeValueModel([], $this->_websiteCode);
            $attributeValues     = $attributeValueModel->getAllAttributeValue([['attribute_id', 'in', $attributeIds]]);

            $attributeModel = new AttributeModel([], $this->_websiteCode);
            $attributes     = $attributeModel->getAllAttribute([['id', 'in', $attributeIds]]);
            foreach ($attributes as $attribute) {
                if ($attribute['attribute_type'] == AttributeModel::IS_PICTURE_ATTRIBUTE) {
                    $hasImageAttribute = true;
                    $imageAttributeId  = $attribute['id'];
                    break;
                }
            }
            $category['hasImageAttribute'] = $hasImageAttribute;
            $category['imageAttributeId']  = $imageAttributeId;

            $activeAttributes = [];
            foreach ($attributes as $key => $attribute) {
                $attributeId = $attribute['id'];
                foreach ($attributeValues as $attributeValue) {
                    if ($attributeValue['attribute_id'] == $attributeId && count($attributeValue) > 0) {
                        if (!isset($activeAttributes[$attributeId])) {
                            $activeAttributes[$attributeId] = $attribute;
                        }

                        $activeAttributes[$attributeId]['values'][] = $attributeValue;
                    }
                }
            }
            $category['attributes'] = $activeAttributes;

            $moduleModule            = new ModuleModel([], $this->_websiteCode);
            $modules                 = $moduleModule->getAllModule();
            $category['module_name'] = $modules[$category['module_id']]['name'];

            // 当前的所有父级
            $categories = $this->_categoryObj->getAllCategory();
            $parents    = $this->_getCurCategoryParents($categories, $id);
            for ($i = count($parents) - 1; $i >= 0; $i--) {
                $category['parents'][] = $parents[$i];
            }

            // 当前的顶级
            $topParent = $parents[count($parents) - 1];
            // 顶级的所有子级
            $children               = [$topParent];
            $children               = array_merge($children, $this->_getCurCategoryChildren($categories, $topParent['id']));
            $category['categories'] = $this->_wrapTitle($children, $modules);

            // url
            $categoryUrls    = $this->_getCategoryUrl($categories);
            $category['url'] = $categoryUrls[$category['id']];
        } catch (Exception $e) {
            logErr('通过主键读取栏目详细信息失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return $category;
    }

    private function _parseAttribute(string $attribute): array
    {
        $res        = [];
        $attributes = explode(',', $attribute);
        foreach ($attributes as $attribute) {
            $values = explode(':', $attribute);
            if (!count($values) || count($values) <= 1) {
                continue;
            }

            $attributeId         = $values[0];
            $attributeValueId    = $values[1];
            $res[$attributeId][] = $attributeValueId;
        }
        return $res;
    }

    public function findCategoryByUri(string $cdnDomain, string $uri, string $attribute = ''): array
    {
        $selectAttributes = $this->_parseAttribute($attribute);

        $uri = '/' . $uri;
        $res = [];
        try {
            $categories = $this->_categoryObj->getAllCategory($cdnDomain);
            foreach ($categories as $category) {
                if ($category['uri'] == $uri) {
                    $res = $category;
                }
            }
            if (empty($res)) {
                return $res;
            }

            $attributeModel = new AttributeModel([], $this->_websiteCode);
            $res            = array_merge($res, $attributeModel->getCategoryAttribute($res['id'], $selectAttributes));
        } catch (Exception $e) {
            logErr('通过uri读取栏目详细信息失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return $res;
    }

    public function getCurCategoryChildrenIds($id): array
    {
        $ids        = [];
        $categories = $this->_categoryObj->getAllCategory();
        $children   = $this->_getCurCategoryChildren($categories, $id);
        foreach ($children as $child) {
            $ids[] = $child['id'];
        }

        return $ids;
    }

    public function updateCategory(string $cdnDomain, int $id, array $data): bool
    {
        try {
            $categories = $this->_categoryObj->getAllCategory();
            $parents    = $this->_getCurCategoryParents($categories, $data['pid']);

            $uris = [];
            for ($i = count($parents) - 1; $i >= 0; $i--) {
                $tempSeoUrl = strtolower($parents[$i]['seo_url']);
                $tempSeoUrl = str_replace(' ', '-', $tempSeoUrl);
                $tempSeoUrl = str_replace('/', '', $tempSeoUrl);
                $uris []    = $tempSeoUrl;
            }

            $seoUrl      = strtolower($data['seo_url']);
            $seoUrl      = str_replace(' ', '-', $seoUrl);
            $seoUrl      = str_replace('/', '', $seoUrl);
            $uris[]      = $seoUrl;
            $data['uri'] = '/' . implode('/', $uris);

            return $this->_categoryObj->updateCategory($cdnDomain, $id, $data);
        } catch (Exception $e) {
            logErr('通过主键更新栏目失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return false;
    }

    public function batchUpdateCategorySort(array $data): bool
    {
        try {
            return (boolean)$this->_categoryObj->batchUpdateCategorySort($data);
        } catch (Exception $e) {
            logErr('通过主键更新栏目排序失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return false;
    }

    public function deleteCategory(int $id): array
    {
        try {
            $category = $this->_categoryObj->findCategoryById($id);
            if (empty($category)) {
                return [self::_RESULT => true, self::_MESSAGE => self::_DELETE_SUCCESS_MESSAGE];
            }

            $children = $this->_categoryObj->findCategoryByPid($id);
            if (!empty($children->toArray())) {
                return [self::_RESULT => false, self::_MESSAGE => self::_DELETE_CATEGORY_HAS_CHILD_ERROR];
            }

            $childCategoryIds = array_merge([$id], $this->getCurCategoryChildrenIds($id));
            $moduleModel      = new ModuleModel([], $this->_websiteCode);
            $moduleOne        = $moduleModel->findModuleById($category['module_id']);
            if (empty($moduleOne)) {
                return [self::_RESULT => false, self::_MESSAGE => self::_SYSTEM_ERROR_MESSAGE];
            }
            $module = $moduleOne->toArray();

            return [self::_RESULT => $this->_categoryObj->deleteCategory($id, $childCategoryIds, $module['code']), self::_MESSAGE => self::_DELETE_SUCCESS_MESSAGE];
        } catch (Exception $e) {
            logErr('通过主键删除栏目失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [self::_RESULT => false, self::_MESSAGE => self::_SYSTEM_ERROR_MESSAGE];
    }

    public function getCategoryTree(string $cdnDomain): array
    {
        try {
            $categories = $this->_categoryObj->getAllCategory();
            return $this->_getCategoryTree($cdnDomain, $categories, 0);
        } catch (Exception $e) {
            logErr('读取栏目树失败(后台)', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [];
    }

    public function getArticleFields(int $categoryId): array
    {
        try {
            $moduleFieldModel = new ModuleFieldModel([], $this->_websiteCode);
            return $moduleFieldModel->getArticleFields($categoryId);
        } catch (Exception $e) {
            logErr('通过栏目id读取文档的所有字段失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [];
    }

    public function getRedirectCategoryId(int $categoryId): int
    {
        if (!$categoryId) {
            return $categoryId;
        }

        $cur        = [];
        $categories = $this->_categoryObj->getAllCategory();
        foreach ($categories as $category) {
            if ($category['id'] == $categoryId) {
                $cur = $category;
                break;
            }
        }
        if (empty($cur)) {
            return 0;
        }

        $children = $this->_getCategoryTree('', $this->_categoryObj->getAllCategory(), $categoryId);

        // 不跳转子栏目
        if ($cur['is_redirect_child'] == CommonBaseModel::CATEGORY_IS_NOT_REDIRECT_CHILD) {
            return $categoryId;
        }

        // 没有子栏目
        if (count($children) == 0) {
            return $categoryId;
        }

        // 跳转子栏目
        foreach ($children as $child) {
            if ($child['is_redirect_child'] == CommonBaseModel::CATEGORY_IS_REDIRECT_CHILD && count($child['children']) > 0) {
                return $this->getRedirectCategoryId($child['children'][0]['id']);
            } else {
                return $child['id'];
            }
        }

        return 0;
    }

    public function getChannels(string $cdnDomain, int $curVisitId, string $type): array
    {
        try {
            $categories    = $this->_categoryObj->getAllCategory();
            $cidParentsIds = $curVisitId ? $this->_getCurCategoryParentsIds($categories, $curVisitId) : [];
            $cidTopId      = count($cidParentsIds) > 0 ? $cidParentsIds[count($cidParentsIds) - 1] : 0;
            $categoryUrls  = $this->_getCategoryUrl($categories);

            $filterCategories = [];
            foreach ($categories as $k => $category) {
                if ($category['status'] == CommonBaseModel::IS_DISABLE_STATUS) {
                    continue;
                }
                $category['url'] = $categoryUrls[$category['id']];
                $category['cur'] = 0;
                if (in_array($category['id'], $cidParentsIds)) {
                    $category['cur'] = 1;
                }
                $filterCategories[] = $category;
            }

            if ($type === 'top') {
                return $this->_getCategoryTree($cdnDomain, $filterCategories, 0);
            }

            if ($type === 'topChildren') {
                return $this->_getCategoryTree($cdnDomain, $filterCategories, $cidTopId);
            }

            if ($type === 'curChildren') {
                return $this->_getCategoryTree($cdnDomain, $filterCategories, $curVisitId);
            }

            return [];
        } catch (\Exception $e) {
            logErr('读取栏目树失败(前台)', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [];
    }

    public function getCategoryUrl(int $cid)
    {
        $categories = $this->_categoryObj->getAllCategory();
        $urlMap     = $this->_getCategoryUrl($categories);
        return $urlMap[$cid] ?? '';
    }

    /*** private methods ***/

    private function _getCategoryUrl(array $categories): array
    {
        $cacheKey     = $this->_websiteCode . '_categoryUrls';
        $categoryUrls = Cache::get($cacheKey);
        if (!empty($categoryUrls)) {
            return $categoryUrls;
        }

        $categoryUrls      = [];
        $needUrlCategories = [];
        $categoryToIdMap   = [];
        foreach ($categories as $category) {
            $redirectCategoryId = $this->getRedirectCategoryId($category['id']);
            $redirectCategory   = $categories[$redirectCategoryId];
            switch ($redirectCategory['type']) {
                case CategoryModel::SINGLE_PAGE:
                    // 单页
                    $moduleModel                                = new ModuleModel([], $this->_websiteCode);
                    $module                                     = $moduleModel->findModuleById($redirectCategory['module_id']);
                    $needUrlCategories[$module['code']][]       = $redirectCategory['id'];
                    $categoryUrls[$category['id']]              = '/';
                    $categoryToIdMap[$redirectCategory['id']][] = $category['id'];
                    break;
                case CategoryModel::LIST_PAGE:
                    // 列表
                    $categoryUrls[$category['id']] = sprintf('%s/p/1.html', $redirectCategory['uri']);
                    break;
                case CategoryModel::COVER_PAGE:
                    // 封面
                    $categoryUrls[$category['id']] = sprintf('%s.html', $redirectCategory['uri']);
                    break;
                case CategoryModel::REDIRECT_PAGE:
                    // 跳转
                    $categoryUrls[$category['id']] = $redirectCategory['go_url'];
                    break;
            }
        }

        $articleMap = [];
        foreach ($needUrlCategories as $code => $ids) {
            $articleModel = new ArticleModel([], $this->_websiteCode, 'article_' . $code);
            $articles     = $articleModel->getArticleList(1, count($ids), [['category_id', 'in', $ids], 'status' => CommonBaseModel::IS_ENABLE_STATUS])->toArray();
            foreach ($articles as $article) {
                $articleMap[$article['category_id']] = $article;
            }
        }

        foreach ($articleMap as $categoryId => $article) {
            $redirectCategory            = $categories[$categoryId];
            $redirectCategoryCreateAtStr = date('Ymd', strtotime($redirectCategory['created_at']));
            $realCategoryIds             = $categoryToIdMap[$categoryId];
            foreach ($realCategoryIds as $realCategoryId) {
                $categoryUrls[$realCategoryId] = sprintf('%s/%s%s.html', $redirectCategory['uri'], $redirectCategoryCreateAtStr, $article['id']);
            }
        }

        Cache::set($cacheKey, $categoryUrls, 3);
        return $categoryUrls;
    }

    private function _getCategoryTree(string $cdnDomain, array $categories, int $pid): array
    {
        $res = [];
        foreach ($categories as $category) {
            if ($category['pid'] == $pid) {
                $one             = [
                    'id'                 => $category['id'],
                    'pid'                => $category['pid'],
                    'title'              => $category['title'],
                    'title_en'           => $category['title_en'],
                    'module_id'          => $category['module_id'],
                    'type'               => $category['type'],
                    'remark'             => $category['remark'],
                    'status'             => $category['status'],
                    'is_redirect_child'  => $category['is_redirect_child'],
                    'introduce_content'  => str_replace('{cdnDomain}', $cdnDomain, base64_encode($category['introduce_content'])),
                    'fullIntroduceImage' => $category['introduce_image'] ? $cdnDomain . $category['introduce_image'] : '',
                    'note'               => str_replace('{cdnDomain}', $cdnDomain, base64_encode($category['note'])),
                    'fullNoteImage'      => $category['note_image'] ? $cdnDomain . $category['note_image'] : '',
                    'url'                => $category['url'] ?? '/',
                    'cur'                => $category['cur'] ?? 0,
                    'fullImage'          => $category['image'] ? $cdnDomain . '/' . $category['image'] : '',
                ];
                $one['children'] = $this->_getCategoryTree($cdnDomain, $categories, $category['id']);
                $res []          = $one;
            }
        }
        return $res;
    }

    private function _wrapTitle(array $categories, array $moduleMap): array
    {
        $categoryLen = count($categories);
        $num         = 1;
        $prefixMap   = [1];
        foreach ($categories as $k => $v) {
            if ($k > 0) {
                if ($categories[$k - 1]['pid'] != $v['pid']) {
                    $num++;
                }
            }

            if (isset($prefixMap[$v['pid']])) {
                $num = $prefixMap[$v['pid']];
            }

            $prefixMap[$v['pid']] = $num;

            $repeatFlag = '';
            for ($i = 0; $i < $num - 1; $i++) {
                if ($i == $num - 2) {
                    if ($k + 1 < $categoryLen && $v['pid'] <= $categories[$k + 1]['pid']) {
                        $repeatFlag .= self::_LEVEL_PREFIX;
                    } else {
                        $repeatFlag .= self::_LAST_LEVEL_PREFIX;
                    }
                } else {
                    $repeatFlag .= self::_FIRST_LEVEL_PREFIX;
                }
            }

            $warpTitle                     = $repeatFlag . $v['title'];
            $categories[$k]['title']       = $warpTitle;
            $categories[$k]['type_name']   = CategoryModel::FIELD_TYPE_NAME_MAP[$v['type']] ?? '';
            $categories[$k]['module_name'] = $moduleMap[$v['module_id']]['name'] ?? '';
            $categories[$k]['status_name'] = CategoryModel::STATUS_IN_NAV_MAP[$v['status']] ?? '';
            $categories[$k]['target_name'] = CategoryModel::TARGET_NAME_MAP[$v['target']] ?? '';
        }

        return $categories;
    }

    public function getCurCategoryParents(int $pid): array
    {
        $categories = $this->_categoryObj->getAllCategory();
        return $this->_getCurCategoryParents($categories, $pid);
    }

    public function clearCategoryCache(): bool
    {
        return $this->_categoryObj->clearCategoryCache();
    }

    private function _getCurCategoryParents(array $categories, int $pid): array
    {
        $res = [];
        foreach ($categories as $category) {
            if ($category['id'] == $pid) {
                $res[] = $category;
                $res   = array_merge($res, $this->_getCurCategoryParents($categories, $category['pid']));
            }
        }

        return $res;
    }

    private function _getCurCategoryParentsIds(array $categories, int $pid): array
    {
        $ids     = [];
        $parents = $this->_getCurCategoryParents($categories, $pid);
        foreach ($parents as $parent) {
            $ids[] = $parent['id'];
        }
        return $ids;
    }

    private function _getCurCategoryChildren(array $categories, int $pid): array
    {
        $res = [];
        foreach ($categories as $category) {
            if ($category['pid'] == $pid) {
                $res[] = $category;
                $res   = array_merge($res, $this->_getCurCategoryChildren($categories, $category['id']));
            }
        }

        return $res;
    }
}
